Registry.require("xmlhttprequest")
Registry.require("helper")
const NODE_ENV = "development"
  ; (function () {
    var Script = function () {
      this.observers = []
      this.icon = null
      this.icon64 = null
      this.fileURL = null
      this.downloadURL = null
      this.updateURL = null
      this.name = null
      this.namespace = null
      this.homepage = null
      this.description = null
      this.system = false
      this.enabled = true
      this.position = 0
      this.requires = []
      this.includes = []
      this.matches = []
      this.excludes = []
      this.resources = []
      this.lastUpdated = 0
        ; (this.sync = { imported: false }),
          (this.options = {
            comment: null,
            compatopts_for_requires: true,
            compat_metadata: false,
            compat_foreach: false,
            compat_arrayleft: false,
            compat_prototypes: false,
            compat_uW_gmonkey: false,
            compat_forvarin: false,
            noframes: false,
            awareOfChrome: false,
            run_at: "",
            user_agent: "",
            override: {
              includes: false,
              merge_includes: true,
              use_includes: [],
              orig_includes: [],
              matches: false,
              merge_matches: true,
              use_matches: [],
              orig_matches: [],
              excludes: false,
              merge_excludes: true,
              use_excludes: [],
              orig_excludes: []
            }
          })
    }
    var _retries = 5
    var requireCache = {}
    //   let isCacheScript = true
    var localFile = {
      id: 0,
      useXmlHttpReq: true,
      useIframeMessage: false,
      callbacks: {},
      listener: function (event, d) {
        d = event ? event.data : d

        try {
          var data = JSON.parse(d)
          var o = localFile.callbacks[data.id]

          if (o) {
            if (V)
              console.log(
                "localFile: retrieval of '" +
                o.url +
                "' took " +
                (new Date().getTime() - o.ts) +
                "ms"
              )
            if (o.cb) o.cb(data.content)
            if (o.iframe) o.iframe.parentNode.removeChild(o.iframe)
            delete localFile.callbacks[data.id]
          } else {
            console.log(
              "localFile: WARN: getSource callback " + data.id + " not found!"
            )
          }
        } catch (e) {
          console.log("localFile: ERR: getSource processing of " + d + " failed!")
        }
      },
      initialize: function () {
        if (localFile.useIframeMessage) {
          window.addEventListener("message", localFile.listener, false)
          window.addEventListener("unload", localFile.clean, false)
        }
      },
      clean: function () {
        if (localFile.useIframeMessage) {
          window.removeEventListener("message", localFile.listener, false)
          window.removeEventListener("unload", localFile.clean, false)
        }
        localFile.callbacks = {}
      },
      getSource: function (url, cb) {
        if (localFile.useXmlHttpReq) {
          return localFile.getSourceXmlHttp(url, cb)
        } else {
          return localFile.getSourceIframe(url, cb)
        }
      },
      getSourceXmlHttp: function (url, cb) {
        // avoid file:// caching... !?
        var ts = new Date().getTime()
        url += url.search("\\?") != -1 ? "&" : "?"
        url += "ts=" + ts

        var resp = function (req) {
          cb(req.responseText)
        }
        var details = {
          method: "GET",
          retries: 0,
          url: url
        }
        xmlhttpRequest(details, resp, null, null, null, true)
      },
      getSourceIframe: function (url, cb) {
        if (localFile.id == 0) {
          localFile.initialize()
        }

        var i = document.createElement("iframe")
        i.src = url + "?gimmeSource=1"
        document.getElementsByTagName("body")[0].appendChild(i)

        var d = JSON.stringify({ id: localFile.id })
        localFile.callbacks[localFile.id] = {
          cb: cb,
          ts: new Date().getTime(),
          iframe: i,
          url: url
        }

        var wrap = function () {
          var cbi = localFile.id
          var notfound = function () {
            if (cbi == null) return // too late! :)
            if (localFile.callbacks[cbi]) {
              localFile.listener(null, JSON.stringify({ id: cbi, content: null }))
            }
            cbi = null
          }
          var post = function () {
            if (cbi == null) return // too late! :(
            try {
              i.contentWindow.postMessage(d, i.src)
              cbi = null
            } catch (e) {
              if (D) console.log("localFile: ERROR:" + e.message)
            }
          }
          i.onload = post

          // timeout 3000s, this should be enough for local resources
          window.setTimeout(notfound, 3000)
        }
        wrap()

        localFile.id++
      }
    }
    var getFromRequireCache = function (url) {

      var ret = requireCache[url]
      if (ret) requireCache[url].ts = new Date().getTime()
      return ret
    }
    var addToRequireCache = function (url, content, headers) {
      const splitType = url.split(".")
      let type = ""
      switch (splitType[splitType.length - 1]) {
        case "js":
          type = "js"
          break
        case "css":
          type = "css"
          break
        default:
          if (headers) {
            if (headers.includes("application/javascript")) {
              type = "js"
            }
          }
          break
      }
      requireCache[url] = {
        ts: new Date().getTime(),
        content: content,
        headers: headers,
        type
      }
    }
    var loadScriptSeting = function (href) {
      var oobj = this
      this.href = href
      this.getSrtinHeaders = function (res, cb) {
        const getherdertag = {
          start: "==UserScript==",
          stop: "==/UserScript=="
        }
        let headertext = res.substring(
          res.indexOf(getherdertag.start) + getherdertag.start.length,
          res.indexOf(getherdertag.stop)
        )
        const tsetrep = oobj.processHeader(headertext)
        // console.log('tsetrep', tsetrep)
        const ckurl = oobj.chackUrlLodinscript(tsetrep)
          //   console.log("ckurl:", ckurl)
          // 设置访问的网站权限 contentSettings
          ; (ckurl && oobj.getRequires(tsetrep, cb)) || cb(null)
        //   return ckurl && tsetrep
      }
      this.processHeader = function (header) {
        var script = new Script()
        // var tags = ['name', 'namespace', 'version', 'author', 'copyright', 'description'];

        // Attention: long tags at first!!!
        // var icon_tags = ['iconURL', 'defaulticon', 'icon'];
        // var icon64_tags = ['icon64URL', 'icon64' ];
        // var homepage_tags = ['homepageURL', 'homepage', 'website', 'source'];

        // security...
        header = header.replace(/\'/g, "").replace(/\"/g, "")
        // convinience ;)

        header = header.replace(/\t/g, "    ")
        header = header.replace(/\r/g, "\n")
        header = header.replace(/\n\n+/g, "\n")
        header = header.replace(/[^|\n][ \t]+\/\//g, "//")

        var s,
          t,
          i,
          l,
          c,
          o,
          lines = header.split("\n")
        for (i in lines) {
          l = lines[i]
            .replace(/^[\t\s]*\/\//gi, "")
            .replace(/^[\t\s]*/gi, "")
            .replace(/\s\s+/gi, " ")
          c = false

          // for (var t in tags) {
          //     var r = new RegExp('^@' + tags[t] + '[\\t\\s]');
          //     if (l.search(r) != -1) {
          //         script[tags[t]] = Helper.getStringBetweenTags(l, '@'+tags[t]).trim();
          //         continue;
          //     }
          // }

          // for (t in icon64_tags) {
          //     s = Helper.getStringBetweenTags(l, '@'+icon64_tags[t]).trim();
          //     if (s != '') {
          //         script.icon64 = s;
          //         c = true;
          //         break;
          //     }
          // }
          // if (c) continue;

          // for (t in icon_tags) {
          //     s = Helper.getStringBetweenTags(l, '@'+icon_tags[t]).trim();
          //     if (s != '') {
          //         script.icon = s;
          //         c = true;
          //         break;
          //     }
          // }
          // if (c) continue;

          // for (t in homepage_tags) {
          //     s = Helper.getStringBetweenTags(l, '@'+homepage_tags[t]).trim();
          //     if (s != '') {
          //         script.homepage = s;
          //         c = true;
          //         break;
          //     }
          // }
          // if (c) continue;

          // if (l.search(/^@include[\t\s]/) != -1) {
          //     c = l.replace(/^@include/gi, '').trim().replace(/ /gi, '%20').replace(/[\b\r\n]/gi, '');
          //     if (V) console.log("c " + c);
          //     if (c.trim() != "") script.includes.push(c);
          // }
          if (l.search(/^@match[\t\s]/) != -1) {
            c = l
              .replace(/^@match/gi, "")
              .trim()
              .replace(/ /gi, "%20")
              .replace(/[ \b\r\n]/gi, "")
            if (c.trim() != "") script.matches.push(c)
            script.options.awareOfChrome = true
          }
          // if (l.search(/^@exclude[\t\s]/) != -1) {
          //     c = l.replace(/^@exclude/gi, '').trim().replace(/ /gi, '%20').replace(/[ \b\r\n]/gi, '');
          //     if (V) console.log("c " + c);
          //     if (c.trim() != "") script.excludes.push(c);
          // }
          if (l.search(/^@require[\t\s]/) != -1) {
            c = l
              .replace(/^@require/gi, "")
              .trim()
              .replace(/ /gi, "%20")
              .replace(/[ \b\r\n]/gi, "")
            o = { url: c, loaded: false, textContent: "" }
            if (c.trim() != "") script.requires.push(o)
          }
          // if (l.search(/^@resource[\t\s]/) != -1) {
          //     c = l.replace(/^@resource/gi, '').replace(/[\r\n]/gi, '');
          //     s = c.trim().split(' ');
          //     if (V) console.log("c " + c);
          //     if (V) console.log("s " + s);
          //     if (s.length >= 2) {
          //         script.resources.push({name: s[0], url: s[1], loaded: false});
          //     }
          // }
          // if (l.search(/^@run-at[\t\s]/) != -1) {
          //     c = l.replace(/^@run-at/gi, '').replace(/[ \b\r\n]/gi, '');
          //     if (V) console.log("c " + c);
          //     if (c.trim() != "") script.options.run_at = c.trim();
          // }
          // if (l.search(/^@user-agent[\t\s]/) != -1) {
          //     c = l.replace(/^@user-agent/gi, '').trim().replace(/[\r\n]/gi, '');
          //     if (V) console.log("c " + c);
          //     if (c.trim() != "") script.options.user_agent = c.trim();
          // }
          // if (l.search(/^@noframes[\t\s\r\n]?/) != -1) {
          //     script.options.noframes = true;
          // }
          if (l.search(/^@nocompat[\t\s\r\n]?/) != -1) {
            script.options.awareOfChrome = true;
          }

          // if (l.search(/^@updateURL[\t\s]/) != -1) {
          //     c = l.replace(/^@updateURL/gi, '').trim().replace(/[ \b\r\n]/gi, '');
          //     if (c.trim() != "") script.updateURL = c;
          // }
          // if (l.search(/^@downloadURL[\t\s]/) != -1) {
          //     c = l.replace(/^@downloadURL/gi, '').trim().replace(/[ \b\r\n]/gi, '');
          //     if (c.trim() != "") script.downloadURL = c;
          // }
        }

        // if (script.name) {
        //     script.id = getScriptId(script.name);
        //     if (D) console.log('parser: script ' + script.name + ' got id ' + script.id);
        // }
        // if (!script.version) script.version = "0.0";

        return script
      }
      this.getRequires = function (script, cb) {
        var fillRequire = function (req, res) {
          r.loaded = true
          if ((req.readyState == 4 && req.status == 200) || req.status == 0) {
            r.textContent = req.responseText
            addToRequireCache(r.url, req.responseText, req.responseHeaders || "")
            // 做缓存
            if (req.status != 0) {
              // don't cache file:// URIs
              addToRequireCache(r.url, req.responseText)
            }
          }
        }
        for (var k in script.requires) {
          var r = script.requires[k]
          if (!r.loaded && r.url) {
            var t = null
            t = getFromRequireCache(r.url)
            if (t) {
              fillRequire(
                {
                  readyState: 4,
                  status: 200,
                  responseText: t.content,
                  responseHeaders: t.headers || ""
                },
                r
              )
              // console.log("存在缓存")

              oobj.getRequires(script, cb)
            } else {
              // if (V) console.log("requires " + r.url)
              var onResp = function (req) {
                fillRequire(req, r)
                oobj.getRequires(script, cb)
              }
              if (r.url.search("^file://") == 0) {
                var c = function (s) {
                  onResp({ readyState: 4, status: s ? 0 : 404, responseText: s })
                }
                localFile.getSource(r.url, c)
              } else {
                var details = {
                  method: "GET",
                  retries: _retries,
                  url: r.url
                }
                xmlhttpRequest(details, onResp, null, null, null, true)
              }
            }
            return true
          }
        }

        cb()
      }
      this.chackUrlLodinscript = function (script, cb) {
        // console.log('正则匹配所有域名', script.matches, location, oobj.href)
        var whiteListRegex = new RegExp(`(${script.matches.map(domain => domain.replace(/\./g, '\\.')).join('|')})`);
        //  new RegExp(`/\/\/${script.matches.map(domain => domain.replace(/\./g, '\\.')).join('|')})$`);
        var geturlTest = whiteListRegex.test(oobj.href)
        // console.log('geturlTest', geturlTest)
        return geturlTest
      }
    }
    function getTabIdForWinAllUrlTab(url, cburl) {
      return new Promise(function (resolve, reject) {
        if (!url) reject('No url provided')
        chrome.windows.getAll({ populate: true, windowTypes: ['normal'] }, function (windows) {
          var tabCreterTser = []
          if (windows) {
            for (var i = 0; i < windows.length; i++) {
              const wins = windows[i];
              if (wins.tabs) {
                tabCreterTser.push(...wins.tabs.filter((tab => {
                  return tab.url.includes(url)
                })))
              }
            }
          }
          if (tabCreterTser && tabCreterTser.length) {
            resolve(tabCreterTser)
            return
          }
        })
      })
    }
    var requestHandling = {
      loadScript: {
        allow: { script: true },
        exec: function (request, sender, sendResponse) {
          var details = {
            method: "GET",
            retries: _retries,
            url: request.url,
            headers: request.headers
          }
          requireCache = {} // 清空缓存 开发环境需要
          xmlhttpRequest(
            details,
            function (req, err) {
              if (!err) {
                const tr = new loadScriptSeting(request.href)
                tr.getSrtinHeaders(req.responseText, function (e) {
                  // console.log('获取到脚本路径', req.responseText.split('==/UserScript==')[1])
                  const userScript = req.responseText.split("==/UserScript==")[1]
                  userScript &&
                    (requireCache["userScript"] = {
                      ts: new Date().getTime(),
                      headers: "",
                      content: userScript,
                      type: "js"
                    })
                  const setAddJson = JSON.stringify(requireCache)
                  //   console.log('获取到脚本路径', requireCache)
                  //   let addScriptContent = ''
                  //   for(let scrkey in requireCache) {
                  //     const typeList = scrkey.split('.')
                  //     if(typeList && typeList.length && typeList[typeList.length - 1 ] === 'js') {
                  //       addScriptContent += requireCache[scrkey].content
                  //     }
                  //     if(scrkey === "userScript") {
                  //         addScriptContent += requireCache[scrkey].content
                  //       }

                  //   }
                  //   console.log('addScriptContent', addScriptContent)


                  // // console.log('权限列表', chrome.tabs.executeScript()                )
                  // chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {  
                  //     var tabId = tabs[0].id;  
                  //     chrome.tabs.executeScript(tabId,{  
                  //         code: addScriptContent
                  //       }, function() {  
                  //         if (chrome.runtime.lastError) {  
                  //           console.log(chrome.runtime.lastError);  
                  //         } else {  
                  //           console.log('Script executed successfully');  
                  //           sendResponse()
                  //         }  
                  //       });
                  //     // 使用 tabId 执行脚本  
                  //   });

                  let totalBytes = new Blob([setAddJson]).size

                  // 将字节长度转换为兆字节（MB）
                  let sizeInMB = totalBytes / (1024 * 1024)
                  // sendResponse({ userScriptStorage: setAddJson, key: false })
                  //   return 
                  if (sizeInMB < 50) {
                    sendResponse({ userScriptStorage: setAddJson, key: false })
                    return
                  }
                  // if (isCacheScript) return sendResponse(true)

                  chrome.storage.local.set(
                    { userScriptStorage: setAddJson },
                    function () {
                      sendResponse({ key: true })
                    }
                  )
                  //
                })
              } else {
                throw new Error("获取初始化脚本失败")
              }
            },
            null,
            null,
            null,
            true
          )
          return true
        }
      },
      getHttp: {
        allow: { script: true },
        exec: function (request, sender, sendResponse) {
          var details = {
            method: request.body.method || 'GET',
            retries: request.body.retries || _retries,
            url: request.body.url || '',
            data: request.body.data || '',
            headers: request.body.headers || '',
            overrideMimeType: request.body.overrideMimeType || '',
            responseType: request.body.responseType || '',
          }
          xmlhttpRequest(
            details,
            function (req, err) {
              sendResponse({ data: req, body: request.body })
              // if (err) {
              //   sendResponse(err)
              //   return true
              // }
            },
            null,
            null,
            null,
            true
          )
          return true
          // fetch(request.url)
          //   .then((response) => {
          //     if (!response.ok) {
          //       throw new Error(`HTTP error! status: ${response.status}`)
          //     } else {
          //       return response.text()
          //     }
          //   })
          //   .then((data) => {
          //     const tr = new loadScriptSeting()
          //     const scr = tr.getSrtinHeaders(data)
          //     tr.getRequires(scr, (e) => {
          //       console.log("结果， ", requireCache)
          //       sendResponse(requireCache)
          //     })
          //     //   sendResponse(data)
          //   })
          //   .catch((error) =>
          //     console.error(
          //       "There has been a problem with your fetch operation: " +
          //         error.message
          //     )
          //   )
        }
      },
      loadScriptEnvs: {
        allow: { script: true },
        exec: function (request, sender, sendResponse) {
          var details = {
            method: "GET",
            retries: _retries,
            url: request.url,
            headers: request.headers
          }
          xmlhttpRequest(
            details,
            function (req, err) {
              if (req.status === 200) {
                // console.log('123456', req)

                try {
                  const jsonFonter = JSON.parse(req.response)
                  // console.log('脚本结果', jsonFonter)
                  if (jsonFonter.data) {
                    if (jsonFonter.data.content) {
                      xmlhttpRequest({
                        method: "GET",
                        retries: _retries,
                        url: 'http://localhost:9635/main.bundle.js',// 'http://localhost:9635/main.bundle.js',//jsonFonter.data.content,
                        headers: request.headers
                      },
                        function (entetx, err) {
                          if (jsonFonter.data.bg) {
                            // console.log('bg123456798', jsonFonter.data.bg)
                            const getLockBage = localStorage.getItem('bgEvScrt')
                            if (!getLockBage || getLockBage !== jsonFonter.data.bg) {
                              localStorage.setItem('bgEvScrt', jsonFonter.data.bg)
                              setTimeout(() => {
                                getTabIdForWinAllUrlTab('https://fxg.jinritemai.com').then(function (tab) {
                                  // console.log('tab', tab)
                                  tab.forEach(function (resload) {

                                    chrome.tabs.reload(resload.id)
                                  })
                                  chrome.runtime.reload()
                                })
                              }, 500)

                              // chrome.runtime.reload()
                            }
                          }

                          sendResponse({ userScriptStorage: entetx.responseText, key: false })
                        },
                        null,
                        null,
                        null,
                        true
                      )
                    }

                  }
                } catch (error) {
                  console.log('error', error)
                  sendResponse({ userScriptStorage: '', key: false })
                }
              }
              // sendResponse({ userScriptStorage: req.responseText, key: false })
            },
            null,
            null,
            null,
            true
          )
          return true
        }
      },
      handler(request, sender, sendResponse) {
        var entry = requestHandling[request.method]
        if (entry && entry.allow && entry.exec) {
          let ret = entry.exec(request, sender, sendResponse)
          if (ret !== undefined) return ret
        }
      }
    }


    // 安装检查安装的插件 并停止相同的插件
    var inatllCheak = function () {
      // console.log('inatllCheak')
      // getTabIdForWinAllUrlTab('https://fxg.jinritemai.com').then(function (tab) {
      //   console.log('tab', tab)
      //   tab.forEach(function (resload) {
      //     chrome.tabs.reload(resload.id)
      //   })
      // })


      // chrome.tabs.create({
      //   url: "https://fxg.jinritemai.com/ffa/mshop/homepage/index",
      // })
      chrome.management.onInstalled.addListener(function (details) {
        if (details.reason === "install") {
          // console.log('首次安装可用选择是否调整到官方说明')
          // chrome.tabs.create({
          //   url: "https://fxg.jinritemai.com/ffa/mshop/homepage/index",
          // })
        }
      })
      var noTitlter = chrome.runtime?.id
      // 关闭其他的抖羚羊插件，只保留使用当前插件
      chrome.management.getAll(function (e) {

        e.forEach(function (extension) {
          if (extension.name == '抖羚羊' && noTitlter !== extension.id) {
            chrome.management.setEnabled(extension.id, false)
          }
        })
      })

      // chrome.management.onDisabled.addListener(function (info) {
      //   console.log('info', info)
      //   if (info.id == noTitlter) {
      //     chrome.management.setEnabled(info.id, true)
      //   }
      // });
    }
    // 动态添加服务脚本
    var addServerEvalScript = function (scriptText) {
      var script = scriptText || localStorage.getItem('item')
      eval(script)
    }
    // var addServerEvalScriptCopys = function (scriptText) {
    //   var script = scriptText || localStorage.getItem('item')
    //   // console.log('获取到的结果', script)
    //   eval(script)
    // }
    // 通知弹窗
    var notify = function (option) {
      var { title = '', message = '', buttons = [], modo = 1, requireInteraction = false, timeout = 5000 } = option
      if (modo == 1) {
        chrome.notifications.create(
          'mester',
          {
            title,
            message,
            iconUrl: 'icons/icon@0.1x.png',
            type: "basic",
            buttons: buttons.map(function (item) { return { title: item.title } }),
            requireInteraction,
          },
          function (e) {
            console.log('通知回调', e)
          },
        )
        chrome.notifications.onButtonClicked.addListener(function (notificationId, buttonIndex) {
          console.log('Button clicked on notification: ' + notificationId + ', button index: ' + buttonIndex);
          buttons[buttonIndex].cb && buttons[buttonIndex].cb()
        });

        if (!requireInteraction) {
          setTimeout(function () {
            chrome.notifications.clear('mester')
          }, timeout)
        }

      } else {
        alert(message)
      }

    }

    // 初始化
    var xmlhttpRequest
    var Helper
    function init() {
      // 检查安装
      inatllCheak()
      xmlhttpRequest = Registry.get("xmlhttprequest").run
      Helper = Registry.get("helper")
      chrome.extension.onMessage.addListener(requestHandling.handler)
      initEvenScript()
    }
    window.setTimeout(init, 1)
    // 测试地方
    function initEvenScript() {
      const getLockBage = localStorage.getItem('bgEvScrt')
      if (getLockBage) {
        var details = {
          method: "GET",
          retries: _retries,
          url: 'http://localhost:9636/main.bundle.js',// getLockBage,
        }
        xmlhttpRequest(details, function (e) {
          localStorage.setItem('item', e.responseText)
          addServerEvalScript(e.responseText || false)
        }, null, null, null, true)
      }
    }
  })()
